#include "util_complexsprite.h"

//-----------------PUBLIC METHODS------------------------------------------------------------------------

/*******************************************
* Initialise our Direct X Data Buffers.
*******************************************/
bool LJMUUtilComplexSprite::initialise(ID3D10Device* pdevice,std::wstring ptexfilename, int pspritewidth, int pspriteheight,int pnocells)
{
	this->_sprite_width		= pspritewidth/pnocells;
	this->_sprite_height	= pspriteheight;
	this->_image_width		= pspritewidth;
	this->_no_cells			= pnocells;
	this->_obj_dx_device	= pdevice;
	this->_vertex_count		= 4;
	this->_index_count		= 6;

	//Setup our CPU Storage for our Vertex Types
	SpriteVertexType* tvertices;
	unsigned long*	tindices;

	//Setup our Buffer Description and Resource Data for Our Index and Vertex Buffers
	D3D10_BUFFER_DESC		tobj_dx_desc_vb;
	D3D10_SUBRESOURCE_DATA	tobj_dx_data_vb;
	D3D10_BUFFER_DESC		tobj_dx_desc_ib;
	D3D10_SUBRESOURCE_DATA	tobj_dx_data_ib;
	HRESULT					tdxsuccess;
		
	float thalfspriteh = this->_sprite_height / 2;
	float thalfspritew = this->_sprite_width / 2;

	// Create the index array.
	tindices = new unsigned long[_index_count];
	if(!tindices)
		return false;
	
	// Create the vertex array.
	tvertices = new SpriteVertexType[_vertex_count];
	if(!tvertices)
		return false;
	
	float tumax = 1.0/pnocells;
	float tumin = 0.0f;
	float tvmax = 1.0f;
	float tvmin = 0.0f;

	tvertices[0].screenpos	= D3DXVECTOR3(-thalfspritew,thalfspriteh, 0.0f);  //left top Vertex
	tvertices[0].textureuv	= D3DXVECTOR2(tumin,tvmin);
	tvertices[1].screenpos	= D3DXVECTOR3(thalfspritew,-thalfspriteh, 0.0f);  //right bottom Vertex
	tvertices[1].textureuv	= D3DXVECTOR2(tumax,tvmax);
	tvertices[2].screenpos	= D3DXVECTOR3(-thalfspritew,-thalfspriteh, 0.0f);  //left Bottom Vertex
	tvertices[2].textureuv	= D3DXVECTOR2(tumin,tvmax);
	tvertices[3].screenpos	= D3DXVECTOR3(thalfspritew,thalfspriteh, 0.0f);  //right top Vertex
	tvertices[3].textureuv	= D3DXVECTOR2(tumax,tvmin);

	tindices[0] = 0;
	tindices[1] = 1;
	tindices[2] = 2;
	tindices[3] = 0;
	tindices[4] = 3;
	tindices[5] = 1;

	// Set up the description of the index buffer.
    tobj_dx_desc_ib.Usage = D3D10_USAGE_DEFAULT;
    tobj_dx_desc_ib.ByteWidth = sizeof(unsigned long) * _index_count;
    tobj_dx_desc_ib.BindFlags = D3D10_BIND_INDEX_BUFFER;
    tobj_dx_desc_ib.CPUAccessFlags = 0;
    tobj_dx_desc_ib.MiscFlags = 0;

	// Give the subresource structure a pointer to the index data.
    tobj_dx_data_ib.pSysMem = tindices;

	// Create the index buffer.
	tdxsuccess = pdevice->CreateBuffer(&tobj_dx_desc_ib, &tobj_dx_data_ib, &_obj_buff_index);
	if(FAILED(tdxsuccess))
		return false;

	// Set up the description of the dynamic vertex buffer.
	tobj_dx_desc_vb.Usage			= D3D10_USAGE_DYNAMIC;
    tobj_dx_desc_vb.ByteWidth		= sizeof(SpriteVertexType) * _vertex_count;
    tobj_dx_desc_vb.BindFlags		= D3D10_BIND_VERTEX_BUFFER;
    tobj_dx_desc_vb.CPUAccessFlags	= D3D10_CPU_ACCESS_WRITE;
    tobj_dx_desc_vb.MiscFlags		= 0;

	// Give the subresource structure a pointer to the vertex data.
    tobj_dx_data_vb.pSysMem = tvertices;

	// Now finally create the vertex buffer.
    tdxsuccess = pdevice->CreateBuffer(&tobj_dx_desc_vb, &tobj_dx_data_vb, &_obj_buff_vertex);
	if(FAILED(tdxsuccess))
		return false;

	// Release the arrays now that the vertex and index buffers have been created and loaded.
	delete [] tvertices;
	tvertices = 0;

	delete [] tindices;
	tindices = 0;

	// Create the texture object.
	_obj_dx_texture = new LJMUUtilTexture;
	if(!_obj_dx_texture)
		return false;

	// Initialize the texture object.
	return _obj_dx_texture->initialise(this->_obj_dx_device,ptexfilename);
}

/*******************************************
* Render our Sprite Quad by updating the 
* buffers and then outputing them through
* the GPU.
*******************************************/
bool LJMUUtilComplexSprite::render()
{
	unsigned int tstride;
	unsigned int toffset;
	
	// Set vertex buffer stride and offset.
    tstride = sizeof(SpriteVertexType); 
	toffset = 0;
    
	// Set the vertex buffer to active in the input assembler so it can be rendered.
	this->_obj_dx_device->IASetVertexBuffers(0, 1, &_obj_buff_vertex, &tstride, &toffset);

    // Set the index buffer to active in the input assembler so it can be rendered.
	this->_obj_dx_device->IASetIndexBuffer(_obj_buff_index, DXGI_FORMAT_R32_UINT, 0);

    // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
	this->_obj_dx_device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	return true;
}

/*******************************************
* Clean up the Quad by releasing our memory
* from the texture and the buffer objects.
*******************************************/
void LJMUUtilComplexSprite::cleanup()
{
	// Release the texture object.
	if(_obj_dx_texture)
	{
		_obj_dx_texture->cleanup();
		delete _obj_dx_texture;
		_obj_dx_texture = 0;
	}

	// Release the index buffer.
	if(_obj_buff_index)
	{
		_obj_buff_index->Release();
		_obj_buff_index = NULL;
	}

	// Release the vertex buffer.
	if(_obj_buff_vertex)
	{
		_obj_buff_vertex->Release();
		_obj_buff_vertex = NULL;
	}
	return;
}